﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Wombat.Core.Diagnostics;
using Wombat.Core.Factories;
using Wombat.Core.Services;

namespace Wombat.Core.Gates
{
    /// <summary>
    /// This gate represents a base class for a web service endpoint gate. WSE gate can be used
    /// in a webservice host as a gateway to input data into the system.
    /// </summary>
    public abstract class ServiceEndpointBaseGate : IGate, ITagValueObservable, IInitializable, IConfigurable, ILongLifeGate, IDiagnosticsObservable, IStartable
    {
        public static class ConfigurationKeys
        {
            public static readonly string EndPointType = "EndPointType";

            public static readonly string BaseEndPointAddress = "BaseEndPointAddress";

            public static readonly string Guid = "Guid";
        }

        private readonly IObservationManager _observationManager;
        private readonly IConfigurationService _configurationService;
        private readonly IDiagnosticsService _diagnosticsService;

        public IObservablePort ObservablePort { get; private set; }

        protected ServiceEndpointBaseGate(IObservationManager observationManager, IConfigurationService configurationService, IDiagnosticsService diagnosticsService)
        {
            _observationManager = observationManager;
            _configurationService = configurationService;
            _diagnosticsService = diagnosticsService;
        }

        protected IDiagnosticsService DiagnosticsService
        {
            get { return _diagnosticsService; }
        }

        #region Implementation of ITagValueObservable

        public IDisposable Subscribe<T>(string pattern, IObserver<T> observer) where T: ITagValue
        {
            return _observationManager.Subscribe(this, pattern, observer);
        }

        #endregion

        #region Implementation of IGate

        public Guid Guid { get; protected set; }
        public IEnumerable<IPort> Ports { get; protected set; }

        #endregion

        #region Implementation of IInitializable

        public virtual void Initialize()
        {
            Configurations = _configurationService.ReadConfigurations(GetType());
            if (Configurations.ContainsKey(ConfigurationKeys.Guid))
                Guid = Guid.Parse((string)Configurations[ConfigurationKeys.Guid].Value);
            ObservablePort = (IObservablePort)PortFactory.Create("ServiceEndPointPort", PortBehavior.Output, this);
            Ports = new[] { ObservablePort };
        }
        
        #endregion

        #region Implementation of IConfigurable

        public IDictionary<string, IConfigurationItem> Configurations { get; private set; }

        #endregion

        #region Implementation of IDisposable

        public void Dispose()
        {
            DisposeService();
        }

        #endregion

        #region Implementation of IDiagnosticsObservable

        public virtual void SubscribeDiagnostics(DiagnosticsLevel level, IObserver<IDiagnosticsMessage> errorObserver)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region interface IStartable - abstract methods

        public abstract Task StartAsync();

        public abstract Task StopAsync();

        #endregion

        protected abstract void DisposeService();

        protected virtual void SendMessage(ITagValue value)
        {
            throw new NotImplementedException();
        }
    }
}
